package edu.gmu.projects.fireresponder.fusionengine;

import java.io.IOException;
import java.io.InputStream;

import android.app.Service;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;
import edu.gmu.projects.fireresponder.comm.MessageCommunicator;
import edu.gmu.projects.fireresponder.comm.UdpBroadcastService;
import edu.gmu.projects.fireresponder.environment.Asset;
import edu.gmu.projects.fireresponder.environment.Location;

public class FusionService extends Service implements IFusionInterface {

	// This is the object that receives interactions from clients. See
	// RemoteService for a more complete example.
	private final IBinder mBinder = new LocalBinder();

	private FusionEngine fusionEngine;

	public FusionEngine getFusionEngine() {
		if (fusionEngine == null) {
			try {
				final InputStream buildingStream = getAssets().open(
						"json/building-data.json");
				final InputStream pathStream = getAssets().open(
						"json/path-data.json");
				final InputStream safespotStream = getAssets().open(
						"json/safespot-data.json");
				fusionEngine = new FusionEngine(buildingStream, pathStream,
						safespotStream);
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return fusionEngine;
	}

	/**
	 * Class for clients to access. Because we know this service always runs in
	 * the same process as its clients, we don't need to deal with IPC.
	 */
	public class LocalBinder extends Binder {
		public FusionService getService() {
			return FusionService.this;
		}
	}

	private UdpBroadcastService udpBroadcastService;
	private ServiceConnection udpBroadcastConnection = new ServiceConnection() {

		public void onServiceConnected(ComponentName className, IBinder service) {
			udpBroadcastService = ((UdpBroadcastService.LocalBinder) service)
					.getService();
			MessageCommunicator.addMessageListener(getFusionEngine());

			Log.i("FusionService", "Connected to UdpBroadcastService");
		}

		public void onServiceDisconnected(ComponentName arg0) {
			udpBroadcastService = null;

			Log.i("FusionService", "Disconnected from UdbBroadcastService");
		}
	};

	public MessageCommunicator getAlertService() {
		return udpBroadcastService.getMessageCommunicator();
	}

	@Override
	public IBinder onBind(Intent arg0) {
		return mBinder;
	}

	@Override
	public void onCreate() {
		super.onCreate();

		Intent intent = new Intent(this, UdpBroadcastService.class);
		bindService(intent, udpBroadcastConnection, BIND_AUTO_CREATE);

		Log.i("FusionService", "Created FusionService service");
	}

	@Override
	public void onDestroy() {
		super.onDestroy();

		unbindService(udpBroadcastConnection);

		Log.i("FusionService", "Destroyed FusionService service");
	}

	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {
		return START_STICKY;
	}

	public double getFireProbability(Location location) {
		return getFusionEngine().getFireProbability(location);
	}

	public double getFireProbability(double latitude, double longitude) {
		return getFusionEngine().getFireProbability(latitude, longitude);
	}

	public double getFireProbability(Location location, int timeInMillis) {
		return getFusionEngine().getFireProbability(location, timeInMillis);
	}

	public double getFireProbability(double latitude, double longitude,
			int timeInMillis) {
		return getFusionEngine().getFireProbability(latitude, longitude,
				timeInMillis);
	}

	public double getPresenceProbability(Location location) {
		return getFusionEngine().getPresenceProbability(location);
	}

	public double getPresenceProbability(double latitude, double longitude) {
		return getFusionEngine().getPresenceProbability(latitude, longitude);
	}

	public double getPresenceProbability(Location location, int timeInMillis) {
		return getFusionEngine().getPresenceProbability(location, timeInMillis);
	}

	public double getPresenceProbability(double latitude, double longitude,
			int timeInMillis) {
		return getFusionEngine().getPresenceProbability(latitude, longitude,
				timeInMillis);
	}

	public void addListener(FusionEngineListener listener) {
		getFusionEngine().addListener(listener);
	}

	public void removeListener(FusionEngineListener listener) {
		getFusionEngine().removeListener(listener);
	}

	public double getFireProbability(Asset asset) {
		return getFusionEngine().getFireProbability(asset);
	}

	public double getFireProbability(Asset asset, int timeInMillis) {
		return getFusionEngine().getFireProbability(asset, timeInMillis);
	}

	public double getPercentageOnFire(double minCertainty, Asset asset) {
		return getFusionEngine().getPercentageOnFire(minCertainty, asset);
	}

	public double getPercentageOnFire(double minCertainty, Asset asset,
			int timeInMillis) {
		return getFusionEngine().getPercentageOnFire(minCertainty, asset,
				timeInMillis);
	}

	public double getPresenceProbability(Asset asset) {
		return getFusionEngine().getPresenceProbability(asset);
	}

	public double getPresenceProbability(Asset asset, int timeInMillis) {
		return getFusionEngine().getPresenceProbability(asset, timeInMillis);
	}

	public double getFireDistance(double latitude, double longitude,
			double minProb) {
		return getFusionEngine().getFireDistance(latitude, longitude, minProb);
	}

	public double getFireDistance(Asset asset, double minProb) {
		return getFusionEngine().getFireDistance(asset, minProb);
	}

	public double getFireDistance(Location location, double minProb) {
		return getFusionEngine().getFireDistance(location, minProb);
	}

}
